#region imports

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Configuration.Assemblies;
using System.Reflection;
using MimeCloud.AssetManagement.Editor.Config;
using MimeCloud.AssetManagement.ProviderServices.Config;
using MimeCloud.AssetManagement.ProviderServices.Data;
using MimeCloud.AssetManagement.ProviderServices.Repository;

#endregion

namespace MimeCloud.AssetManagement.ProviderServices
{
    public class AssetManagerConfig : ConfigurationSection
    {
        private static AssetManagerConfig _section;

        public static AssetManagerConfig Current
        {
            get
            {
                if ( _section == null )
                {
                    _section = ( AssetManagerConfig ) ConfigurationManager.GetSection ( "AssetManagerSection" );
                }

                return _section;
            }
        }

        #region configuration properies

        [ConfigurationProperty ( "AssetWriterProvider" ,
            DefaultValue = "MimeCloud.AssetManager.DataProvider.Sql.MSSqlProvider, MimeCloud.AssetManager.DataProvider.Sql" ,
            IsKey = false ,
            IsRequired = true )]
        public string AssetWriterProvider
        {
            get { return ( ( string ) ( base [ "AssetWriterProvider" ] ) ); }
            set { base [ "AssetWriterProvider" ] = value; }
        }

        [ConfigurationProperty ( "AssetReaderProvider" ,
            DefaultValue = "MimeCloud.AssetManager.DataProvider.Sql.MSSqlProvider, MimeCloud.AssetManager.DataProvider.Sql" ,
            IsKey = false ,
            IsRequired = true )]
        public string AssetReaderProvider
        {
            get { return ( ( string ) ( base [ "AssetReaderProvider" ] ) ); }
            set { base [ "AssetReaderProvider" ] = value; }
        }
        [ConfigurationProperty("AssetSearcherProvider",
            DefaultValue = "MimeCloud.AssetManager.DataProvider.Sql.SqlSearcher, MimeCloud.AssetManager.DataProvider.Sql" ,
            IsKey = false ,
            IsRequired = true )]
        public string AssetSearcherProvider
        {
            get { return ((string)(base["AssetSearcherProvider"])); }
            set { base["AssetSearcherProvider"] = value; }
        }
        /// <summary>
        /// The list of repositories to access
        /// </summary>
        [ConfigurationProperty("repositoryDetails", IsRequired = true)]
        public RepositoryDetailCollection CurrentRepositoryDetailCollection
        {
            get { return (RepositoryDetailCollection)(this["repositoryDetails"]); }
        }

        #endregion

        private Dictionary<string, IRepositoryManager> _repoManagers = null;
        public Dictionary<string, IRepositoryManager> RepositoryManagers
        {
            get
            {
                CheckInitialiseRepositories();
                return _repoManagers;
            }
        }

        public IRepositoryManager DefaultRepositoryManager
        {
            get
            {
                CheckInitialiseRepositories();
                return _repoManagers[CurrentRepositoryDetailCollection.DefaultRespositoryName];
            }
        }

        private void CheckInitialiseRepositories()
        {
            if (_repoManagers == null)
            {
                _repoManagers = new Dictionary<string, IRepositoryManager>();
                foreach (RepositoryDetail detail in CurrentRepositoryDetailCollection)
                {
                    _repoManagers.Add(detail.Name,GetRepositoryManager(detail));
                }
            }
        }

        private IRepositoryManager GetRepositoryManager(RepositoryDetail repositorySettings)
        {
            IRepositoryManager assetReaderFactory = null;

            var strDelegate = repositorySettings.Type.Split(',')[0];
            var strAssembly = repositorySettings.Type.Split(',')[1];
            var asm = Assembly.Load(strAssembly.Trim());
            var t = asm.GetType(strDelegate.Trim());
            if (t != null)
            {
                if (t.GetInterface(typeof (IRepositoryManager).FullName) == null)
                {
                    throw new Exception(
                        "IRepositoryManager delegate must implement the interface MimeCloud.AssetManager.ProviderServices.Repository.IRepositoryManager");
                }
            }
            else
            {
                throw new Exception(
                    string.Format("IRepositoryManager delegate type '{0}' not found in assembly '{1}'.", strDelegate,
                                  strAssembly));
            }

            assetReaderFactory = (IRepositoryManager) Activator.CreateInstance(t);
            
            //set properties
            assetReaderFactory.RepositoryKey = repositorySettings.Name;
            assetReaderFactory.RepositorySettings = new Dictionary<string, string>();
            foreach (KeyValueConfigurationElement setting in repositorySettings.RepositorySettings)
            {
                assetReaderFactory.RepositorySettings.Add(setting.Key,setting.Value);
            }

            return assetReaderFactory;
        }

        public static IAssetReaderFactory GetAssetReaderProvider ( )
        {
            IAssetReaderFactory assetReaderFactory = null;
            if ( Current != null && Current.AssetReaderProvider != null )
            {
                var strDelegate = Current.AssetReaderProvider.Split ( ',' ) [ 0 ];
                var strAssembly = Current.AssetReaderProvider.Split ( ',' ) [ 1 ];
                var asm = Assembly.Load ( strAssembly.Trim ( ) );
                var t = asm.GetType ( strDelegate.Trim ( ) );
                if ( t != null )
                {
                    if ( t.GetInterface ( typeof ( IAssetReaderFactory ).FullName ) == null )
                    {
                        throw new Exception (
                            "AssetReaderProvider delegate must implement the interface MimeCloud.AssetManager.ProviderServices.Data.ICommentReaderFactory" );
                    }
                }
                else
                {
                    throw new Exception (
                        string.Format ( "AssetReaderProvider delegate type '{0}' not found in assembly '{1}'." , strDelegate ,
                                      strAssembly ) );
                }

                assetReaderFactory = ( IAssetReaderFactory ) Activator.CreateInstance ( t );
            }
            else
            {
                throw new Exception ( "AssetReader provider configuration not found" );
            }
            return assetReaderFactory;
        }
        public static IAssetSearcher GetAssetSearcherProvider()
        {
            IAssetSearcher assetReaderFactory = null;
            if (Current != null && Current.AssetSearcherProvider != null)
            {
                var strDelegate = Current.AssetSearcherProvider.Split(',')[0];
                var strAssembly = Current.AssetSearcherProvider.Split(',')[1];
                var asm = Assembly.Load(strAssembly.Trim());
                var t = asm.GetType(strDelegate.Trim());
                if (t != null)
                {
                    if (t.GetInterface(typeof(IAssetSearcher).FullName) == null)
                    {
                        throw new Exception(
                            "IAssetSearcher delegate must implement the interface MimeCloud.AssetManager.ProviderServices.Data.IAssetSearcher");
                    }
                }
                else
                {
                    throw new Exception(
                        string.Format("IAssetSearcher delegate type '{0}' not found in assembly '{1}'.", strDelegate,
                                      strAssembly));
                }

                assetReaderFactory = (IAssetSearcher)Activator.CreateInstance(t);
            }
            else
            {
                throw new Exception("IAssetSearcher provider configuration not found");
            }
            return assetReaderFactory;
        }
        public static IAssetWriterFactory GetAssetWriterProvider ( )
        {
            IAssetWriterFactory assetWriterFactory = null;
            if ( Current != null && Current.AssetWriterProvider != null )
            {
                var delegateName = Current.AssetWriterProvider.Split ( ',' ) [ 0 ];
                var assemblyName = Current.AssetWriterProvider.Split ( ',' ) [ 1 ];
                var asm = Assembly.Load ( assemblyName.Trim ( ) );
                var t = asm.GetType ( delegateName.Trim ( ) );
                if ( t != null )
                {
                    if ( t.GetInterface ( typeof ( IAssetWriterFactory ).FullName ) == null )
                    {
                        throw new Exception ( "AssetWriterProvider delegate must implement the interface MimeCloud.Community.Commenting.ProviderServices.Data.IAssetWriterFactory" );
                    }
                }
                else
                {
                    throw new Exception ( string.Format ( "AssetWriterProvider delegate type '{0}' not found in assembly '{1}'." , delegateName , assemblyName ) );
                }

                assetWriterFactory = ( IAssetWriterFactory ) Activator.CreateInstance ( t );
            }
            else
            {
                throw new Exception ( "AssetWriter provider configuration not found" );
            }

            return assetWriterFactory;
        }
    }
}

